嗨一大家,記得之前我們在屬性綁定章節,有講到 CSS 樣式可以使用 v-bind 屬性綁定樣式嗎~
但官方文件後來卻提到了:
但是,在處理比較複雜的綁定時,通過拼接生成字符串是麻煩且易出錯的。因此,Vue 專門為 class 和 style 的 v-bind 用法提供了特殊的功能增強。除了字符串外,表達式的值也可以是對象或數組。
看起來是因為字串容易凸槌,所以專門為 CSS 樣式提供了「陣列」及「物件」的綁定方式。![]()
我們先今天來看看 class 的綁定方式吧~
v-bind:class=""
簡寫
:class=""
屬性綁定的特點就是「響應性」,當綁定的數據 "" 中的值改變時,Vue 就會負責處理所有的 UI 更新。
"" 中定義一個物件 {}。
其 key 為:要綁定的 class 名稱;value 為:值。
:class="{ class 名稱: 值 }"
設置 value 為真假值,可以實現該 class 是否要被渲染上去。
<div :class="{ active: isActive }"></div>
// 這邊的 active 是自定義的 class 名稱
isActive 值若設為真值,active 這個 class 將會被渲染上去:
<script setup>
import { ref } from "vue";
const isActive = ref(true);
</script>

isActive 值若設為假值,active 這個 class 將不會被渲染上去:
<script setup>
import { ref } from "vue";
const isActive = ref(false);
</script>

將 class 屬性綁定為「物件」後,可以更靈活的實現控制多個 class 的需求。
我們可以透過以下方式操作物件值:
computed
:class 指令可與「一般」的 class 屬性綁定共存喔。
接下來的範例,將會以這個需求為假設,去使用不同方式達成~
畫面上有這些元素:
- 正方形
- 按鈕
- 圓形(點選按鈕後才出現)
點選 2. 後 1. 會變成 3.
先思考一下,為什麼要走到這步?為什麼要用物件綁定 class 屬性?
因為想要達成:動態控制多個 class。
也就是想做到:在達到某些操作之後,依賴 Vue 的響應性功能動態更改多個樣式的狀態,並達成介面渲染更新。
因此這邊就會搭配 Vue 的響應式系統去操作哦!
開始!
:class="{ key1: value1, key2: value2 }"
// key 可以有很多組,代表不同的 class 狀態,用逗號 (,) 分隔。
我們可以這樣做:
<script setup>
import { ref } from "vue";
const isSquare = ref(true);
const isCircle = ref(false);
function changeColor() {
isCircle.value = true;
}
</script>
<template>
<h3 class="static" :class="{ square: isSquare, circle: isCircle }"></h3>
<br />
<button @click="changeColor">點我變圓形</button>
</template>
<style>
.static {
width: 200px;
height: 200px;
border: 2px solid black;
}
.square {
background-color: rgb(227, 223, 255);
}
.circle {
background-color: rgb(173, 165, 227);
border-radius: 50%;
}
</style>
一步一步來解釋~
<script setup>
import { ref } from "vue";
const isSquare = ref(true);
const isCircle = ref(false);
function changeColor() {
isCircle.value = true;
}
</script>
以上 <script setup>:
isSquare 使用 ref 綁定,設置值為 true。isCircle 使用 ref 綁定,設置值為 false 。changeColor 函式,將 isCircle 的值,設為 true(isCircle.value 做的是對 RefImpl 物件取值)。<template>
<h3 class="static" :class="{ square: isSquare, circle: isCircle }"></h3>
<br />
<button @click="changeColor">點我變圓形</button>
</template>
模板中:
class 樣式 static。:class="{ square: isSquare, circle: isCircle }":"" 中綁定物件,並使用「多個鍵值組」的方式綁定 square: isSquare 和 circle: isCircle 的 class 狀態。button 使用 v-on 簡寫綁定 @click 事件,點按鈕會觸發 changeColor 這個表達式。<style>
.static {
width: 200px;
height: 200px;
border: 2px solid black;
}
.square {
background-color: rgb(227, 223, 255);
}
.circle {
background-color: rgb(173, 165, 227);
border-radius: 50%;
}
</style>
也看一下我們為 square 和 circle 兩個 class 定義的樣式。
點選按鈕!
注意看看,瀏覽器上的 class 屬性多了 circle。
因為 changeColor 函式執行,將 isCircle 的值設為 true,因此會加上 .circle 這個樣式,就看到設置的背景顏色和圓形啦!~

如果我們將剛剛 {} 中的「兩個鍵值組」包成 reactive 物件呢?
複習!
reactive 的特性是:可讓其中的物件直接具有響應性,當這些屬性的值改變時,依賴於這些屬性的其他響應式系統(如 ref)也會自動更新喔。
直接來實作:
<script setup>
import { reactive, ref } from "vue";
const isSquare = ref(true);
const isCircle = ref(false);
const shape = reactive({
square: isSquare,
circle: isCircle,
});
function changeColor() {
shape.circle = true;
}
</script>
<template>
<h3 class="static" :class="shape"></h3>
<br />
<button @click="changeColor">點我變圓形</button>
</template>
我們需要注意以下部分:
reactive 包裹一個物件,在物件中定義要綁定的 class 屬性和值(也就是把在 "" 的 多個鍵值組 包起來)。changeColor 函式更改 circle: isCircle 的值方式,需要調整:透過取得 shape 物件中的 circle 屬性,做更改。<template> 中 <h3 class="static" :class="shape"></h3> 的 class 指令直接綁定為 shape 物件。會是看到同樣的結果!

複習一下 computed 的特點,會在「其依賴的數據變化時」自動重新更新。
而官方表示將它綁定於 class 屬性是一個常見且很有用的技巧哦!
我們可以利用 computed 來創造一個「依賴於響應式系統」的物件,這樣當依賴的資料發生變化時,可以自動偵測並渲染相應的 class。
如果今天我可愛的客戶想動態切換兩個形狀呢?點按鈕正方形會變圓形,再點一次又變回正方形呢?
開完會 PM 可能會先寫需求變更單。
你老闆可能會說:要多久,他加班可以做完嗎?
我們可以這樣施法:
<script setup>
import { ref, computed } from "vue";
const shapeType = ref("square");
const classObj = computed(() => ({
square: shapeType.value === "square",
circle: shapeType.value === "circle",
}));
function changeShape() {
shapeType.value = shapeType.value === "square" ? "circle" : "square";
}
</script>
<template>
<h3 class="static" :class="classObj"></h3>
<br />
<button @click="changeShape">點我變形</button>
</template>
shapeType 為:ref 狀態 "square"(預設圖形為正方形)。classObj 變數為 computed 物件,其中有:square 屬性:值為 shapeType.value === "square"
circle 屬性:值為 shapeType.value === "circlechangeShape 函式:shapeType.value 的值。shapeType.value = shapeType.value === "square" ? "circle" : "square"; 中會判斷 shapeType.value === "square" 為 true/false,再將 shapeType.value 指定為 "circle"/"square"。shapeType.value 是 "square",將會重新賦值為 "circle"。):class 指令綁定為 classObj 物件。<button> 綁定 @click 事件,執行 changeShape 這個表達式。腦中模擬一下,預想,我們會因為以下步驟,達成需求情境:
shapeType 預設是 square,一開始圖形會是正方形。changeShape 會 將 shapeType.value 改為"circle"。ref() 中的值會更新為 "circle"。classObj 是 computed 屬性,它會重新計算,此時將渲染出 "circle" 這個 class。看一下瀏覽器上呈現的結果:
補上 console.log 來印出 按下按鈕後,物件內的 _value:
function changeShape() {
shapeType.value = shapeType.value === "square" ? "circle" : "square";
console.log(`變形了`, shapeType);
}
console.log(`第一次`, shapeType);
再觀察一下!
"" 中定義一個陣列 []。
:class="[ 陣列元素, 陣列元素 ]"
這邊的陣列元素可以用「響應式狀態」綁定 class 的名稱。
因此我們又可以魔改範例:
<script setup>
import { ref } from "vue";
const isSquare = ref("square");
const isCircle = ref(false);
function changeColor() {
isCircle.value = "circle";
}
</script>
<template>
<h3 class="static" :class="[isSquare, isCircle]"></h3>
<br />
<button @click="changeColor">點我變圓形</button>
</template>
:class="[isSquare, isCircle] 中:
isSquare 為 "square",會渲染對應的這個 class 。isCircle 為 false,特別注意,這個值會被轉為空字串 "",將不會渲染。isCircle 的值會改為 "circle" 才會渲染。這邊可以注意一下和「綁定物件」的區別,在這邊如果我們定義:在點了按鈕後,將 isCircle 更改為 true:
const isSquare = ref("square");
const isCircle = ref(false);
function changeColor() {
// 錯誤示範
isCircle.value = true;
console.log(isCircle.value);
}
是不會渲染的!
原因在於,陣列的元素並非完全由真假值控制動態切換,而是直接對應到特定的 class。
即使陣列元素是預期接受 class 名稱,但若是綁定了 JS 定義中的假值:false、null、undefined、0 和 "",它們都會被視為不渲染該該元素。
當我們想把 isCircle 的渲染的條件以三元表達式定義,也可以這麼寫:
<h3 class="static" :class="[isSquare, isCircle ? 'circle' : '']"></h3>
官方文件:然而,這可能在有多個依賴條件的 class 時會有些冗長。因此你也可以在數組中嵌套對象
物件中的鍵值組,可以用真假值或邏輯來控制動態切換。
<h3 class="static" :class="[isSquare, { circle: isCircle }]"></h3>
isSquare:直接放 isSquare 的名稱,會始終渲染對應的 class。isCircle:用布林值來控制是否添加 circle 這個 class。
官方文件:本節假設你已經有 Vue 組件的知識基礎。如果沒有,你也可以暫時跳過,以後再閱讀。
(我先跳過 XD,之後再回來補齊)
有基礎的大家可以坐火箭飛過去!
這邊的範例和實作讓我寫到有點腦袋小爆炸!!
但是也體驗到了如果寫得好,就會很靈活的表現~~~(真是太好了)
明天我們來看下篇 style 囉!![]()
https://github.com/Jamixcs/2024iThome-jamixcs/tree/main/src/components/day17